/**
 * +----------------------------------------------------------------------
 * | 「e家宜业」
 * +----------------------------------------------------------------------
 * | Copyright (c) 2020-2024 https://www.chowa.cn All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed 未经授权禁止移除「e家宜业」和「卓佤科技」相关版权
 * +----------------------------------------------------------------------
 * | Author: contact@chowa.cn
 * +----------------------------------------------------------------------
 */

Component({
    properties: {
        /**
         * 图片路径
         */
        imgSrc: {
            type: String
        },
        /**
         * 裁剪框高度
         */
        height: {
            type: Number,
            value: 200
        },
        /**
         * 裁剪框宽度
         */
        width: {
            type: Number,
            value: 200
        },
        /**
         * 裁剪框最小尺寸
         */
        min_width: {
            type: Number,
            value: 100
        },
        min_height: {
            type: Number,
            value: 100
        },
        /**
         * 裁剪框最大尺寸
         */
        max_width: {
            type: Number,
            value: 300
        },
        max_height: {
            type: Number,
            value: 300
        },
        /**
         * 裁剪框禁止拖动
         */
        disable_width: {
            type: Boolean,
            value: false
        },
        disable_height: {
            type: Boolean,
            value: false
        },
        /**
         * 锁定裁剪框比例
         */
        disable_ratio: {
            type: Boolean,
            value: false
        },
        /**
         * 生成的图片尺寸相对剪裁框的比例
         */
        export_scale: {
            type: Number,
            value: 3
        },
        /**
         * 生成的图片质量0-1
         */
        quality: {
            type: Number,
            value: 1
        },
        cut_top: {
            type: Number,
            value: null
        },
        cut_left: {
            type: Number,
            value: null
        },
        /**
         * canvas上边距（不设置默认不显示）
         */
        canvas_top: {
            type: Number,
            value: null
        },
        /**
         * canvas左边距（不设置默认不显示）
         */
        canvas_left: {
            type: Number,
            value: null
        },
        /**
         * 图片宽度
         */
        img_width: {
            type: null,
            value: null
        },
        /**
         * 图片高度
         */
        img_height: {
            type: null,
            value: null
        },
        /**
         * 图片缩放比
         */
        scale: {
            type: Number,
            value: 1
        },
        /**
         * 图片旋转角度
         */
        angle: {
            type: Number,
            value: 0
        },
        /**
         * 最小缩放比
         */
        min_scale: {
            type: Number,
            value: 0.5
        },
        /**
         * 最大缩放比
         */
        max_scale: {
            type: Number,
            value: 2
        },
        /**
         * 是否禁用旋转
         */
        disable_rotate: {
            type: Boolean,
            value: false
        },
        /**
         * 是否限制移动范围(剪裁框只能在图片内)
         */
        limit_move: {
            type: Boolean,
            value: false
        }
    },
    data: {
        el: 'cw-image-cropper', //暂时无用
        info: wx.getSystemInfoSync(),
        MOVE_THROTTLE: null, //触摸移动节流settimeout
        MOVE_THROTTLE_FLAG: true, //节流标识
        INIT_IMGWIDTH: 0, //图片设置尺寸,此值不变（记录最初设定的尺寸）
        INIT_IMGHEIGHT: 0, //图片设置尺寸,此值不变（记录最初设定的尺寸）
        TIME_BG: null, //背景变暗延时函数
        TIME_CUT_CENTER: null,
        _touch_img_relative: [
            {
                x: 0,
                y: 0
            }
        ], //鼠标和图片中心的相对位置
        _flag_cut_touch: false, //是否是拖动裁剪框
        _hypotenuse_length: 0, //双指触摸时斜边长度
        _flag_img_endtouch: false, //是否结束触摸
        _flag_bright: true, //背景是否亮
        _canvas_overflow: true, //canvas缩略图是否在屏幕外面
        _canvas_width: 200,
        _canvas_height: 200,
        origin_x: 0.5, //图片旋转中心
        origin_y: 0.5, //图片旋转中心
        _cut_animation: false, //是否开启图片和裁剪框过渡
        _img_top: wx.getSystemInfoSync().windowHeight / 2, //图片上边距
        _img_left: wx.getSystemInfoSync().windowWidth / 2, //图片左边距
        watch: {
            //监听截取框宽高变化
            width(value, that) {
                if (value < that.data.min_width) {
                    that.setData({
                        width: that.data.min_width
                    });
                }
                that._computeCutSize();
            },
            height(value, that) {
                if (value < that.data.min_height) {
                    that.setData({
                        height: that.data.min_height
                    });
                }
                that._computeCutSize();
            },
            angle(value, that) {
                //停止居中裁剪框，继续修改图片位置
                that._moveStop();
                if (that.data.limit_move) {
                    if (that.data.angle % 90) {
                        that.setData({
                            angle: Math.round(that.data.angle / 90) * 90
                        });
                        return;
                    }
                }
            },
            _cut_animation(value, that) {
                //开启过渡300毫秒之后自动关闭
                clearTimeout(that.data._cut_animation_time);
                if (value) {
                    that.data._cut_animation_time = setTimeout(() => {
                        that.setData({
                            _cut_animation: false
                        });
                    }, 300);
                }
            },
            limit_move(value, that) {
                if (value) {
                    if (that.data.angle % 90) {
                        that.setData({
                            angle: Math.round(that.data.angle / 90) * 90
                        });
                    }
                    that._imgMarginDetectionScale();
                    !that.data._canvas_overflow && that._draw();
                }
            },
            canvas_top(value, that) {
                that._canvasDetectionPosition();
            },
            canvas_left(value, that) {
                that._canvasDetectionPosition();
            },
            imgSrc(value, that) {
                that.pushImg();
            },
            cut_top(value, that) {
                that._cutDetectionPosition();
                if (that.data.limit_move) {
                    !that.data._canvas_overflow && that._draw();
                }
            },
            cut_left(value, that) {
                that._cutDetectionPosition();
                if (that.data.limit_move) {
                    !that.data._canvas_overflow && that._draw();
                }
            }
        }
    },
    attached() {
        this.data.info = wx.getSystemInfoSync();

        //启用数据监听
        this._watcher();
        this.data.INIT_IMGWIDTH = this.data.img_width;
        this.data.INIT_IMGHEIGHT = this.data.img_height;
        this.setData({
            _canvas_height: this.data.height,
            _canvas_width: this.data.width
        });
        this._initCanvas();
        this.data.imgSrc && (this.data.imgSrc = this.data.imgSrc);
        //根据开发者设置的图片目标尺寸计算实际尺寸
        this._initImageSize();
        //设置裁剪框大小>设置图片尺寸>绘制canvas
        this._computeCutSize();
        //检查裁剪框是否在范围内
        this._cutDetectionPosition();
        //检查canvas是否在范围内
        this._canvasDetectionPosition();
        //初始化完成
        this.triggerEvent('load', {
            cropper: this
        });
    },
    methods: {
        /**
         * 上传图片
         */
        upload() {
            let that = this;
            wx.chooseMedia({
                count: 1,
                mediaType: ['image'],
                sizeType: ['original', 'compressed'],
                sourceType: ['album', 'camera'],
                success: res => {
                    const tempFilePaths = res.tempFiles[0].tempFilePath;
                    that.pushImg(tempFilePaths);
                },
                fail: () => {
                    wx.navigateBack({ delta: 1 });
                }
            });
        },
        /**
         * 返回图片信息
         */
        getImg(getCallback) {
            this._draw(() => {
                wx.canvasToTempFilePath(
                    {
                        width: this.data.width * this.data.export_scale,
                        height: Math.round(this.data.height * this.data.export_scale),
                        destWidth: this.data.width * this.data.export_scale,
                        destHeight: Math.round(this.data.height) * this.data.export_scale,
                        fileType: 'jpg',
                        quality: this.data.quality,
                        canvasId: this.data.el,
                        success: res => {
                            getCallback({
                                url: res.tempFilePath,
                                width: this.data.width * this.data.export_scale,
                                height: this.data.height * this.data.export_scale
                            });
                        }
                    },
                    this
                );
            });
        },
        /**
         * 设置图片动画
         * {
         *    x:10,//图片在原有基础上向下移动10px
         *    y:10,//图片在原有基础上向右移动10px
         *    angle:10,//图片在原有基础上旋转10deg
         *    scale:0.5,//图片在原有基础上增加0.5倍
         * }
         */
        setTransform(transform) {
            if (!transform) return;
            if (!this.data.disable_rotate) {
                this.setData({
                    angle: transform.angle ? this.data.angle + transform.angle : this.data.angle
                });
            }
            var scale = this.data.scale;
            if (transform.scale) {
                scale = this.data.scale + transform.scale;
                scale = scale <= this.data.min_scale ? this.data.min_scale : scale;
                scale = scale >= this.data.max_scale ? this.data.max_scale : scale;
            }
            this.data.scale = scale;
            let cutX = this.data.cut_left;
            let cutY = this.data.cut_top;
            if (transform.cutX) {
                this.setData({
                    cut_left: cutX + transform.cutX
                });
                this.data.watch.cut_left(null, this);
            }
            if (transform.cutY) {
                this.setData({
                    cut_top: cutY + transform.cutY
                });
                this.data.watch.cut_top(null, this);
            }
            this.data._img_top = transform.y ? this.data._img_top + transform.y : this.data._img_top;
            this.data._img_left = transform.x ? this.data._img_left + transform.x : this.data._img_left;
            //图像边缘检测,防止截取到空白
            this._imgMarginDetectionScale();
            //停止居中裁剪框，继续修改图片位置
            this._moveDuring();
            this.setData({
                scale: this.data.scale,
                _img_top: this.data._img_top,
                _img_left: this.data._img_left
            });
            !this.data._canvas_overflow && this._draw();
            //可以居中裁剪框了
            this._moveStop(); //结束操作
        },
        /**
         * 设置剪裁框位置
         */
        setCutXY(x, y) {
            this.setData({
                cut_top: y,
                cut_left: x
            });
        },
        /**
         * 设置剪裁框尺寸
         */
        setCutSize(w, h) {
            this.setData({
                width: w,
                height: h
            });
            this._computeCutSize();
        },
        /**
         * 设置剪裁框和图片居中
         */
        setCutCenter() {
            let cut_top =
                (this.data.info.windowHeight -
                    this.data.height -
                    (this.data.info.screenHeight - this.data.info.safeArea.bottom) -
                    44) *
                0.5;
            let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;
            //顺序不能变
            this.setData({
                _img_top: this.data._img_top - this.data.cut_top + cut_top,
                cut_top: cut_top, //截取的框上边距
                _img_left: this.data._img_left - this.data.cut_left + cut_left,
                cut_left: cut_left //截取的框左边距
            });
        },
        _setCutCenter() {
            let cut_top =
                (this.data.info.windowHeight -
                    this.data.height -
                    (this.data.info.screenHeight - this.data.info.safeArea.bottom) -
                    44) *
                0.5;
            let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;
            this.setData({
                cut_top: cut_top, //截取的框上边距
                cut_left: cut_left //截取的框左边距
            });
        },
        /**
         * 设置剪裁框宽度-即将废弃
         */
        setWidth(width) {
            this.setData({
                width: width
            });
            this._computeCutSize();
        },
        /**
         * 设置剪裁框高度-即将废弃
         */
        setHeight(height) {
            this.setData({
                height: height
            });
            this._computeCutSize();
        },
        /**
         * 是否锁定旋转
         */
        setDisableRotate(value) {
            this.data.disable_rotate = value;
        },
        /**
         * 是否限制移动
         */
        setLimitMove(value) {
            this.setData({
                _cut_animation: true,
                limit_move: !!value
            });
        },
        /**
         * 初始化图片，包括位置、大小、旋转角度
         */
        imgReset() {
            const info = wx.getSystemInfoSync();

            this.setData({
                scale: 1,
                angle: 0,
                _img_top: (info.windowHeight - (info.screenHeight - info.safeArea.bottom) - 44) / 2,
                _img_left: info.windowWidth / 2
            });
        },
        /**
         * 加载（更换）图片
         */
        pushImg(src) {
            if (src) {
                this.setData({
                    imgSrc: src
                });
                //发现是手动赋值直接返回，交给watch处理
                return;
            }

            // getImageInfo接口传入 src: '' 会导致内存泄漏

            if (!this.data.imgSrc) return;
            wx.getImageInfo({
                src: this.data.imgSrc,
                success: res => {
                    this.data.imageObject = res;
                    //图片非本地路径需要换成本地路径
                    if (this.data.imgSrc.search(/tmp/) == -1) {
                        this.setData({
                            imgSrc: res.path
                        });
                    }
                    //计算最后图片尺寸
                    this._imgComputeSize();
                    if (this.data.limit_move) {
                        //限制移动，不留空白处理
                        this._imgMarginDetectionScale();
                    }
                    this._draw();
                },
                fail: err => {
                    this.setData({
                        imgSrc: ''
                    });
                }
            });
        },
        imageLoad(e) {
            setTimeout(() => {
                this.triggerEvent('imageload', this.data.imageObject);
            }, 1000);
        },
        /**
         * 设置图片放大缩小
         */
        setScale(scale) {
            if (!scale) return;
            this.setData({
                scale: scale
            });
            !this.data._canvas_overflow && this._draw();
        },
        /**
         * 设置图片旋转角度
         */
        setAngle(angle) {
            if (!angle) return;
            this.setData({
                _cut_animation: true,
                angle: angle
            });
            this._imgMarginDetectionScale();
            !this.data._canvas_overflow && this._draw();
        },
        _initCanvas() {
            //初始化canvas
            if (!this.data.ctx) {
                this.data.ctx = wx.createCanvasContext('cw-image-cropper', this);
            }
        },
        /**
         * 根据开发者设置的图片目标尺寸计算实际尺寸
         */
        _initImageSize() {
            //处理宽高特殊单位 %>px
            if (
                this.data.INIT_IMGWIDTH &&
                typeof this.data.INIT_IMGWIDTH == 'string' &&
                this.data.INIT_IMGWIDTH.indexOf('%') != -1
            ) {
                let width = this.data.INIT_IMGWIDTH.replace('%', '');
                this.data.INIT_IMGWIDTH = this.data.img_width = (this.data.info.windowWidth / 100) * width;
            }
            if (
                this.data.INIT_IMGHEIGHT &&
                typeof this.data.INIT_IMGHEIGHT == 'string' &&
                this.data.INIT_IMGHEIGHT.indexOf('%') != -1
            ) {
                let height = this.data.img_height.replace('%', '');
                this.data.INIT_IMGHEIGHT = this.data.img_height = (this.data.info.windowHeight / 100) * height;
            }
        },
        /**
         * 检测剪裁框位置是否在允许的范围内(屏幕内)
         */
        _cutDetectionPosition() {
            let _cutDetectionPositionTop = () => {
                    //检测上边距是否在范围内
                    if (this.data.cut_top < 0) {
                        this.setData({
                            cut_top: 0
                        });
                    }
                    if (this.data.cut_top > this.data.info.windowHeight - this.data.height) {
                        this.setData({
                            cut_top: this.data.info.windowHeight - this.data.height
                        });
                    }
                },
                _cutDetectionPositionLeft = () => {
                    //检测左边距是否在范围内
                    if (this.data.cut_left < 0) {
                        this.setData({
                            cut_left: 0
                        });
                    }
                    if (this.data.cut_left > this.data.info.windowWidth - this.data.width) {
                        this.setData({
                            cut_left: this.data.info.windowWidth - this.data.width
                        });
                    }
                };
            //裁剪框坐标处理（如果只写一个参数则另一个默认为0，都不写默认居中）
            if (this.data.cut_top == null && this.data.cut_left == null) {
                this._setCutCenter();
            } else if (this.data.cut_top != null && this.data.cut_left != null) {
                _cutDetectionPositionTop();
                _cutDetectionPositionLeft();
            } else if (this.data.cut_top != null && this.data.cut_left == null) {
                _cutDetectionPositionTop();
                this.setData({
                    cut_left: (this.data.info.windowWidth - this.data.width) / 2
                });
            } else if (this.data.cut_top == null && this.data.cut_left != null) {
                _cutDetectionPositionLeft();
                this.setData({
                    cut_top: (this.data.info.windowHeight - this.data.height) / 2
                });
            }
        },
        /**
         * 检测canvas位置是否在允许的范围内(屏幕内)如果在屏幕外则不开启实时渲染
         * 如果只写一个参数则另一个默认为0，都不写默认超出屏幕外
         */
        _canvasDetectionPosition() {
            if (this.data.canvas_top == null && this.data.canvas_left == null) {
                this.data._canvas_overflow = false;
                this.setData({
                    canvas_top: -5000,
                    canvas_left: -5000
                });
            } else if (this.data.canvas_top != null && this.data.canvas_left != null) {
                if (this.data.canvas_top < -this.data.height || this.data.canvas_top > this.data.info.windowHeight) {
                    this.data._canvas_overflow = true;
                } else {
                    this.data._canvas_overflow = false;
                }
            } else if (this.data.canvas_top != null && this.data.canvas_left == null) {
                this.setData({
                    canvas_left: 0
                });
            } else if (this.data.canvas_top == null && this.data.canvas_left != null) {
                this.setData({
                    canvas_top: 0
                });
                if (this.data.canvas_left < -this.data.width || this.data.canvas_left > this.data.info.windowWidth) {
                    this.data._canvas_overflow = true;
                } else {
                    this.data._canvas_overflow = false;
                }
            }
        },
        /**
         * 图片边缘检测-位置
         */
        _imgMarginDetectionPosition(scale) {
            if (!this.data.limit_move) return;
            let left = this.data._img_left;
            let top = this.data._img_top;
            var scale = scale || this.data.scale;
            let img_width = this.data.img_width;
            let img_height = this.data.img_height;
            if ((this.data.angle / 90) % 2) {
                img_width = this.data.img_height;
                img_height = this.data.img_width;
            }
            left =
                this.data.cut_left + (img_width * scale) / 2 >= left
                    ? left
                    : this.data.cut_left + (img_width * scale) / 2;
            left =
                this.data.cut_left + this.data.width - (img_width * scale) / 2 <= left
                    ? left
                    : this.data.cut_left + this.data.width - (img_width * scale) / 2;
            top =
                this.data.cut_top + (img_height * scale) / 2 >= top
                    ? top
                    : this.data.cut_top + (img_height * scale) / 2;
            top =
                this.data.cut_top + this.data.height - (img_height * scale) / 2 <= top
                    ? top
                    : this.data.cut_top + this.data.height - (img_height * scale) / 2;
            this.setData({
                _img_left: left,
                _img_top: top,
                scale: scale
            });
        },
        /**
         * 图片边缘检测-缩放
         */
        _imgMarginDetectionScale() {
            if (!this.data.limit_move) return;
            let scale = this.data.scale;
            let img_width = this.data.img_width;
            let img_height = this.data.img_height;
            if ((this.data.angle / 90) % 2) {
                img_width = this.data.img_height;
                img_height = this.data.img_width;
            }
            if (img_width * scale < this.data.width) {
                scale = this.data.width / img_width;
            }
            if (img_height * scale < this.data.height) {
                scale = Math.max(scale, this.data.height / img_height);
            }
            this._imgMarginDetectionPosition(scale);
        },
        _setData(obj) {
            let data = {};
            for (var key in obj) {
                if (this.data[key] != obj[key]) {
                    data[key] = obj[key];
                }
            }
            this.setData(data);
            return data;
        },
        /**
         * 计算图片尺寸
         */
        _imgComputeSize() {
            let img_width = this.data.img_width,
                img_height = this.data.img_height;
            if (!this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {
                //默认按图片最小边 = 对应裁剪框尺寸
                img_width = this.data.imageObject.width;
                img_height = this.data.imageObject.height;
                if (img_width / img_height > this.data.width / this.data.height) {
                    img_height = this.data.height;
                    img_width = (this.data.imageObject.width / this.data.imageObject.height) * img_height;
                } else {
                    img_width = this.data.width;
                    img_height = (this.data.imageObject.height / this.data.imageObject.width) * img_width;
                }
            } else if (this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {
                img_width = (this.data.imageObject.width / this.data.imageObject.height) * this.data.INIT_IMGHEIGHT;
            } else if (!this.data.INIT_IMGHEIGHT && this.data.INIT_IMGWIDTH) {
                img_height = (this.data.imageObject.height / this.data.imageObject.width) * this.data.INIT_IMGWIDTH;
            }
            this.setData({
                img_width: img_width,
                img_height: img_height
            });
        },
        //改变截取框大小
        _computeCutSize() {
            if (this.data.width > this.data.info.windowWidth) {
                this.setData({
                    width: this.data.info.windowWidth
                });
            } else if (this.data.width + this.data.cut_left > this.data.info.windowWidth) {
                this.setData({
                    cut_left: this.data.info.windowWidth - this.data.cut_left
                });
            }
            if (this.data.height > this.data.info.windowHeight) {
                this.setData({
                    height: this.data.info.windowHeight
                });
            } else if (this.data.height + this.data.cut_top > this.data.info.windowHeight) {
                this.setData({
                    cut_top: this.data.info.windowHeight - this.data.cut_top
                });
            }
            !this.data._canvas_overflow && this._draw();
        },
        //开始触摸
        _start(event) {
            this.data._flag_img_endtouch = false;
            if (event.touches.length == 1) {
                //单指拖动
                this.data._touch_img_relative[0] = {
                    x: event.touches[0].clientX - this.data._img_left,
                    y: event.touches[0].clientY - this.data._img_top
                };
            } else {
                //双指放大
                let width = Math.abs(event.touches[0].clientX - event.touches[1].clientX);
                let height = Math.abs(event.touches[0].clientY - event.touches[1].clientY);
                this.data._touch_img_relative = [
                    {
                        x: event.touches[0].clientX - this.data._img_left,
                        y: event.touches[0].clientY - this.data._img_top
                    },
                    {
                        x: event.touches[1].clientX - this.data._img_left,
                        y: event.touches[1].clientY - this.data._img_top
                    }
                ];
                this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
            }
            !this.data._canvas_overflow && this._draw();
        },
        _move_throttle() {
            //安卓需要节流
            if (this.data.info.platform == 'android') {
                clearTimeout(this.data.MOVE_THROTTLE);
                this.data.MOVE_THROTTLE = setTimeout(() => {
                    this.data.MOVE_THROTTLE_FLAG = true;
                }, 1000 / 40);
                return this.data.MOVE_THROTTLE_FLAG;
            } else {
                this.data.MOVE_THROTTLE_FLAG = true;
            }
        },
        _move(event) {
            if (this.data._flag_img_endtouch || !this.data.MOVE_THROTTLE_FLAG) return;
            this.data.MOVE_THROTTLE_FLAG = false;
            this._move_throttle();
            this._moveDuring();
            if (event.touches.length == 1) {
                //单指拖动
                let left = event.touches[0].clientX - this.data._touch_img_relative[0].x,
                    top = event.touches[0].clientY - this.data._touch_img_relative[0].y;
                //图像边缘检测,防止截取到空白
                this.data._img_left = left;
                this.data._img_top = top;
                this._imgMarginDetectionPosition();
                this.setData({
                    _img_left: this.data._img_left,
                    _img_top: this.data._img_top
                });
            } else {
                //双指放大
                let width = Math.abs(event.touches[0].clientX - event.touches[1].clientX),
                    height = Math.abs(event.touches[0].clientY - event.touches[1].clientY),
                    hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
                    scale = this.data.scale * (hypotenuse / this.data._hypotenuse_length),
                    current_deg = 0;
                scale = scale <= this.data.min_scale ? this.data.min_scale : scale;
                scale = scale >= this.data.max_scale ? this.data.max_scale : scale;
                //图像边缘检测,防止截取到空白
                this.data.scale = scale;
                this._imgMarginDetectionScale();
                //双指旋转(如果没禁用旋转)
                let _touch_img_relative = [
                    {
                        x: event.touches[0].clientX - this.data._img_left,
                        y: event.touches[0].clientY - this.data._img_top
                    },
                    {
                        x: event.touches[1].clientX - this.data._img_left,
                        y: event.touches[1].clientY - this.data._img_top
                    }
                ];
                if (!this.data.disable_rotate) {
                    let first_atan = (180 / Math.PI) * Math.atan2(_touch_img_relative[0].y, _touch_img_relative[0].x);
                    let first_atan_old =
                        (180 / Math.PI) *
                        Math.atan2(this.data._touch_img_relative[0].y, this.data._touch_img_relative[0].x);
                    let second_atan = (180 / Math.PI) * Math.atan2(_touch_img_relative[1].y, _touch_img_relative[1].x);
                    let second_atan_old =
                        (180 / Math.PI) *
                        Math.atan2(this.data._touch_img_relative[1].y, this.data._touch_img_relative[1].x);
                    //当前旋转的角度
                    let first_deg = first_atan - first_atan_old,
                        second_deg = second_atan - second_atan_old;
                    if (first_deg != 0) {
                        current_deg = first_deg;
                    } else if (second_deg != 0) {
                        current_deg = second_deg;
                    }
                }
                this.data._touch_img_relative = _touch_img_relative;
                this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
                //更新视图
                this.setData({
                    angle: this.data.angle + current_deg,
                    scale: this.data.scale
                });
            }
            !this.data._canvas_overflow && this._draw();
        },
        //结束操作
        _end(event) {
            this.data._flag_img_endtouch = true;
            this._moveStop();
        },
        //点击中间剪裁框处理
        _click() {
            if (!this.data.imgSrc) {
                //调起上传
                this.upload();
                return;
            }
            // shit

            this._draw(() => {
                //生成图片并回调
                wx.canvasToTempFilePath(
                    {
                        width: this.data.width * this.data.export_scale,
                        height: Math.round(this.data.height * this.data.export_scale),
                        destWidth: this.data.width * this.data.export_scale,
                        destHeight: Math.round(this.data.height) * this.data.export_scale,
                        fileType: 'jpg',
                        quality: this.data.quality,
                        canvasId: this.data.el,
                        success: res => {
                            this.triggerEvent('tapcut', {
                                url: res.tempFilePath,
                                width: this.data.width * this.data.export_scale,
                                height: this.data.height * this.data.export_scale
                            });
                        }
                    },
                    this
                );
            });
        },
        //渲染
        _draw(callback) {
            if (!this.data.imgSrc) return;
            let draw = () => {
                //图片实际大小
                let img_width = this.data.img_width * this.data.scale * this.data.export_scale;
                let img_height = this.data.img_height * this.data.scale * this.data.export_scale;
                //canvas和图片的相对距离
                var xpos = this.data._img_left - this.data.cut_left;
                var ypos = this.data._img_top - this.data.cut_top;
                //旋转画布
                this.data.ctx.translate(xpos * this.data.export_scale, ypos * this.data.export_scale);
                this.data.ctx.rotate((this.data.angle * Math.PI) / 180);
                this.data.ctx.drawImage(this.data.imgSrc, -img_width / 2, -img_height / 2, img_width, img_height);
                this.data.ctx.draw(false, () => {
                    callback && callback();
                });
            };
            if (this.data.ctx.width != this.data.width || this.data.ctx.height != this.data.height) {
                //优化拖动裁剪框，所以必须把宽高设置放在离用户触发渲染最近的地方
                this.setData(
                    {
                        _canvas_height: this.data.height,
                        _canvas_width: this.data.width
                    },
                    () => {
                        //延迟40毫秒防止点击过快出现拉伸或裁剪过多
                        setTimeout(() => {
                            draw();
                        }, 40);
                    }
                );
            } else {
                draw();
            }
        },
        //裁剪框处理
        _cutTouchMove(e) {
            if (this.data._flag_cut_touch && this.data.MOVE_THROTTLE_FLAG) {
                if (this.data.disable_ratio && (this.data.disable_width || this.data.disable_height)) return;
                //节流
                this.data.MOVE_THROTTLE_FLAG = false;
                this._move_throttle();
                let width = this.data.width,
                    height = this.data.height,
                    cut_top = this.data.cut_top,
                    cut_left = this.data.cut_left,
                    size_correct = () => {
                        width =
                            width <= this.data.max_width
                                ? width >= this.data.min_width
                                    ? width
                                    : this.data.min_width
                                : this.data.max_width;
                        height =
                            height <= this.data.max_height
                                ? height >= this.data.min_height
                                    ? height
                                    : this.data.min_height
                                : this.data.max_height;
                    },
                    size_inspect = () => {
                        if (
                            (width > this.data.max_width ||
                                width < this.data.min_width ||
                                height > this.data.max_height ||
                                height < this.data.min_height) &&
                            this.data.disable_ratio
                        ) {
                            size_correct();
                            return false;
                        } else {
                            size_correct();
                            return true;
                        }
                    };
                height =
                    this.data.CUT_START.height +
                    (this.data.CUT_START.corner > 1 && this.data.CUT_START.corner < 4 ? 1 : -1) *
                        (this.data.CUT_START.y - e.touches[0].clientY);
                switch (this.data.CUT_START.corner) {
                    case 1:
                        width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;
                        if (this.data.disable_ratio) {
                            height = width / (this.data.width / this.data.height);
                        }
                        if (!size_inspect()) return;
                        cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width);
                        break;
                    case 2:
                        width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;
                        if (this.data.disable_ratio) {
                            height = width / (this.data.width / this.data.height);
                        }
                        if (!size_inspect()) return;
                        cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height);
                        cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width);
                        break;
                    case 3:
                        width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;
                        if (this.data.disable_ratio) {
                            height = width / (this.data.width / this.data.height);
                        }
                        if (!size_inspect()) return;
                        cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height);
                        break;
                    case 4:
                        width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;
                        if (this.data.disable_ratio) {
                            height = width / (this.data.width / this.data.height);
                        }
                        if (!size_inspect()) return;
                        break;
                }
                if (!this.data.disable_width && !this.data.disable_height) {
                    this.setData({
                        width: width,
                        cut_left: cut_left,
                        height: height,
                        cut_top: cut_top
                    });
                } else if (!this.data.disable_width) {
                    this.setData({
                        width: width,
                        cut_left: cut_left
                    });
                } else if (!this.data.disable_height) {
                    this.setData({
                        height: height,
                        cut_top: cut_top
                    });
                }
                this._imgMarginDetectionScale();
            }
        },
        _cutTouchStart(e) {
            let currentX = e.touches[0].clientX;
            let currentY = e.touches[0].clientY;
            let cutbox_top4 = this.data.cut_top + this.data.height - 30;
            let cutbox_bottom4 = this.data.cut_top + this.data.height + 20;
            let cutbox_left4 = this.data.cut_left + this.data.width - 30;
            let cutbox_right4 = this.data.cut_left + this.data.width + 30;

            let cutbox_top3 = this.data.cut_top - 30;
            let cutbox_bottom3 = this.data.cut_top + 30;
            let cutbox_left3 = this.data.cut_left + this.data.width - 30;
            let cutbox_right3 = this.data.cut_left + this.data.width + 30;

            let cutbox_top2 = this.data.cut_top - 30;
            let cutbox_bottom2 = this.data.cut_top + 30;
            let cutbox_left2 = this.data.cut_left - 30;
            let cutbox_right2 = this.data.cut_left + 30;

            let cutbox_top1 = this.data.cut_top + this.data.height - 30;
            let cutbox_bottom1 = this.data.cut_top + this.data.height + 30;
            let cutbox_left1 = this.data.cut_left - 30;
            let cutbox_right1 = this.data.cut_left + 30;
            if (
                currentX > cutbox_left4 &&
                currentX < cutbox_right4 &&
                currentY > cutbox_top4 &&
                currentY < cutbox_bottom4
            ) {
                this._moveDuring();
                this.data._flag_cut_touch = true;
                this.data._flag_img_endtouch = true;
                this.data.CUT_START = {
                    width: this.data.width,
                    height: this.data.height,
                    x: currentX,
                    y: currentY,
                    corner: 4
                };
            } else if (
                currentX > cutbox_left3 &&
                currentX < cutbox_right3 &&
                currentY > cutbox_top3 &&
                currentY < cutbox_bottom3
            ) {
                this._moveDuring();
                this.data._flag_cut_touch = true;
                this.data._flag_img_endtouch = true;
                this.data.CUT_START = {
                    width: this.data.width,
                    height: this.data.height,
                    x: currentX,
                    y: currentY,
                    cut_top: this.data.cut_top,
                    cut_left: this.data.cut_left,
                    corner: 3
                };
            } else if (
                currentX > cutbox_left2 &&
                currentX < cutbox_right2 &&
                currentY > cutbox_top2 &&
                currentY < cutbox_bottom2
            ) {
                this._moveDuring();
                this.data._flag_cut_touch = true;
                this.data._flag_img_endtouch = true;
                this.data.CUT_START = {
                    width: this.data.width,
                    height: this.data.height,
                    cut_top: this.data.cut_top,
                    cut_left: this.data.cut_left,
                    x: currentX,
                    y: currentY,
                    corner: 2
                };
            } else if (
                currentX > cutbox_left1 &&
                currentX < cutbox_right1 &&
                currentY > cutbox_top1 &&
                currentY < cutbox_bottom1
            ) {
                this._moveDuring();
                this.data._flag_cut_touch = true;
                this.data._flag_img_endtouch = true;
                this.data.CUT_START = {
                    width: this.data.width,
                    height: this.data.height,
                    cut_top: this.data.cut_top,
                    cut_left: this.data.cut_left,
                    x: currentX,
                    y: currentY,
                    corner: 1
                };
            }
        },
        _cutTouchEnd(e) {
            this._moveStop();
            this.data._flag_cut_touch = false;
        },
        //停止移动时需要做的操作
        _moveStop() {
            //清空之前的自动居中延迟函数并添加最新的
            clearTimeout(this.data.TIME_CUT_CENTER);
            this.data.TIME_CUT_CENTER = setTimeout(() => {
                //动画启动
                if (!this.data._cut_animation) {
                    this.setData({
                        _cut_animation: true
                    });
                }
                this.setCutCenter();
            }, 1000);
            //清空之前的背景变化延迟函数并添加最新的
            clearTimeout(this.data.TIME_BG);
            this.data.TIME_BG = setTimeout(() => {
                if (this.data._flag_bright) {
                    this.setData({
                        _flag_bright: false
                    });
                }
            }, 2000);
        },
        //移动中
        _moveDuring() {
            //清空之前的自动居中延迟函数
            clearTimeout(this.data.TIME_CUT_CENTER);
            //清空之前的背景变化延迟函数
            clearTimeout(this.data.TIME_BG);
            //高亮背景
            if (!this.data._flag_bright) {
                this.setData({
                    _flag_bright: true
                });
            }
        },
        //监听器
        _watcher() {
            Object.keys(this.data).forEach(v => {
                this._observe(this.data, v, this.data.watch[v]);
            });
        },
        _observe(obj, key, watchFun) {
            var val = obj[key];
            Object.defineProperty(obj, key, {
                configurable: true,
                enumerable: true,
                set: value => {
                    val = value;
                    watchFun && watchFun(val, this);
                },
                get() {
                    if (
                        val &&
                        '_img_top|img_left||width|height|min_width|max_width|min_height|max_height|export_scale|cut_top|cut_left|canvas_top|canvas_left|img_width|img_height|scale|angle|min_scale|max_scale'.indexOf(
                            key
                        ) != -1
                    ) {
                        let ret = parseFloat(parseFloat(val).toFixed(3));
                        if (typeof val == 'string' && val.indexOf('%') != -1) {
                            ret += '%';
                        }
                        return ret;
                    }
                    return val;
                }
            });
        },
        _preventTouchMove() {}
    }
});
